package com.thememaker.lockstyle.parsii;

import com.thememaker.lockstyle.control.LayoutComponentUtils;
import com.thememaker.lockstyle.parsii.eval.Expression;
import com.thememaker.lockstyle.parsii.eval.Parser;
import com.thememaker.lockstyle.parsii.eval.Scope;
import com.thememaker.lockstyle.parsii.tokenizer.ParseException;
import javafx.util.Pair;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Calendar;

/**
 * Created by jiajun.jiang on 2018/2/22.
 */
public class ExpressionUtils {
    private static ExpressionUtils expressionUtils;
    private Scope scope;
    private Expression parsiiExpr;
    private double screen_height, screen_width;

    public double getScreen_height() {
        return screen_height;
    }

    public void setScreen_height(double screen_height) {
        this.screen_height = screen_height;
    }

    public double getScreen_width() {
        return screen_width;
    }

    public void setScreen_width(double screen_width) {
        this.screen_width = screen_width;
    }

    private ExpressionUtils() {

    }

    public static ExpressionUtils getInstance(double screen_width, double screen_height) {
        if (expressionUtils == null) {
            expressionUtils = new ExpressionUtils();
        }
        expressionUtils.setScreen_width(screen_width);
        expressionUtils.setScreen_height(screen_height);
        expressionUtils.InitExpreesion(screen_width, screen_height);
        return expressionUtils;
    }

    private void InitExpreesion(double screen_width, double screen_height) {
        scope = new Scope();
        Calendar calendar = Calendar.getInstance();
        scope.getVariable("year").setValue(calendar.get(Calendar.YEAR));
        scope.getVariable("month").setValue(calendar.get(Calendar.MONTH));
        scope.getVariable("date").setValue(calendar.get(Calendar.DATE));
        scope.getVariable("day_of_week").setValue(calendar.get(Calendar.DAY_OF_WEEK));
        if (LayoutComponentUtils.switcheTime == true) {
            scope.getVariable("hour12").setValue(calendar.get(Calendar.HOUR));
            scope.getVariable("hour24").setValue(calendar.get(Calendar.HOUR));
        } else {
            scope.getVariable("hour12").setValue(calendar.get(Calendar.HOUR_OF_DAY));
            scope.getVariable("hour24").setValue(calendar.get(Calendar.HOUR_OF_DAY));
        }
//        scope.getVariable("hour24").setValue(calendar.get(Calendar.HOUR_OF_DAY));
//        scope.getVariable("hour12").setValue(calendar.get(Calendar.HOUR));
        scope.getVariable("minute").setValue(calendar.get(Calendar.MINUTE));
        scope.getVariable("second").setValue(calendar.get(Calendar.SECOND));
        scope.getVariable("ampm").setValue(calendar.get(Calendar.AM_PM));
        scope.getVariable("time_format").setValue(1);
        scope.getVariable("screen_width").setValue(screen_width);
        scope.getVariable("screen_height").setValue(screen_height);
        scope.getVariable("battery_state").setValue(1);
    }

    public void addVariable(String name, double value) {
        if (scope == null) {
            InitExpreesion(getScreen_width(), getScreen_height());
        }
        scope.getVariable(name).setValue(value);
    }

    public double parseExpr(String exp) {
        if (scope == null) {
            InitExpreesion(getScreen_width(), getScreen_height());
        }
        try {
            if (exp.contains("#")) {
                parsiiExpr = Parser.parse(exp.replace("#", "").replace(".", ""), scope);
            } else {
                parsiiExpr = Parser.parse(exp, scope);
            }
            return parsiiExpr.evaluate();

        } catch (ParseException e) {
            e.printStackTrace();
            return -9999;
        }
//        return 0;
    }

    public boolean isConstant(String exp) {
        if (scope == null) {
            InitExpreesion(getScreen_width(), getScreen_height());
        }
        try {
            parsiiExpr = Parser.parse(exp.replace("#", "").replace(".", ""), scope);
            return parsiiExpr.isConstant();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static ExpressionUtils getInstance(double screen_width, double screen_height, Pair<LocalDate, LocalTime> pair) {
        if (expressionUtils == null) {
            expressionUtils = new ExpressionUtils();
        }
        expressionUtils.setScreen_width(screen_width);
        expressionUtils.setScreen_height(screen_height);
        expressionUtils.InitExpreesion(screen_width, screen_height, pair);
        return expressionUtils;
    }

    private void InitExpreesion(double screen_width, double screen_height, Pair<LocalDate, LocalTime> pair) {
        LocalDate date = pair.getKey();
        LocalTime time = pair.getValue();
        scope = new Scope();
        Calendar calendar = Calendar.getInstance();
        if (date == null) {
            scope.getVariable("year").setValue(calendar.get(Calendar.YEAR));
            scope.getVariable("month").setValue(calendar.get(Calendar.MONTH));
            scope.getVariable("date").setValue(calendar.get(Calendar.DATE));
            scope.getVariable("day_of_week").setValue(calendar.get(Calendar.DAY_OF_WEEK));
        } else {
            scope.getVariable("year").setValue(date.getYear());
            scope.getVariable("month").setValue(date.getMonthValue() - 1);
            scope.getVariable("date").setValue(date.getDayOfMonth());
            if (date.getDayOfWeek().getValue() == 7) {
                scope.getVariable("day_of_week").setValue(1);
            } else {
                scope.getVariable("day_of_week").setValue(date.getDayOfWeek().getValue() + 1);
            }
        }
        if (time == null) {
            if (LayoutComponentUtils.switcheTime) {
                scope.getVariable("hour12").setValue(calendar.get(Calendar.HOUR));
                scope.getVariable("hour24").setValue(calendar.get(Calendar.HOUR));
            } else {
                scope.getVariable("hour12").setValue(calendar.get(Calendar.HOUR_OF_DAY));
                scope.getVariable("hour24").setValue(calendar.get(Calendar.HOUR_OF_DAY));
            }
//            scope.getVariable("hour12").setValue(calendar.get(Calendar.HOUR));
//            scope.getVariable("hour24").setValue(calendar.get(Calendar.HOUR));
            scope.getVariable("minute").setValue(calendar.get(Calendar.MINUTE));
            scope.getVariable("second").setValue(calendar.get(Calendar.SECOND));
            scope.getVariable("ampm").setValue(calendar.get(Calendar.AM_PM));
            scope.getVariable("time_format").setValue(1);
        } else {
            int times = time.getHour();
            if (LayoutComponentUtils.switcheTime && time.getHour() > 11) {
                times = time.getHour() - 12;
            }
            scope.getVariable("hour12").setValue(times);
            scope.getVariable("hour24").setValue(times);
            scope.getVariable("minute").setValue(time.getMinute());
            scope.getVariable("second").setValue(time.getSecond());
            scope.getVariable("ampm").setValue(calendar.get(Calendar.AM_PM));
            scope.getVariable("time_format").setValue(1);
        }
        scope.getVariable("screen_width").setValue(screen_width);
        scope.getVariable("screen_height").setValue(screen_height);
        scope.getVariable("battery_state").setValue(1);
    }
}
